home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************
- * lindner
- * 3.3
- * 1993/04/15 04:48:09
- * /home/mudhoney/GopherSrc/CVS/gopher+/gopherd/ftp.c,v
- * Exp
- *
- * Paul Lindner, University of Minnesota CIS.
- *
- * Copyright 1991, 1992 by the Regents of the University of Minnesota
- * see the file "Copyright" in the distribution for conditions of use.
- *********************************************************************
- * MODULE: ftp.c
- * Routines to translate gopher protocol to ftp protocol.
- *********************************************************************
- * Revision History:
- * ftp.c,v
- * Revision 3.3 1993/04/15 04:48:09 lindner
- * Debug code from Mitra
- *
- * Revision 3.2 1993/03/24 20:15:06 lindner
- * FTP gateway now gets filetypes from gopherd.conf
- *
- * Revision 3.1.1.1 1993/02/11 18:02:51 lindner
- * Gopher+1.2beta release
- *
- * Revision 1.2 1993/01/11 23:18:09 lindner
- * Changed password to be the host of the remote client, not the gateway.
- *
- * Revision 1.1 1992/12/10 23:13:27 lindner
- * gopher 1.1 release
- *
- *
- *********************************************************************/
-
-
- /* -------------------------------------------------
- * g2fd.c Gopher to FTP gateway daemon.
- * Version 0.3 Hacked up: April 1992. Farhad Anklesaria.
- * Based on a Perl story by John Ladwig.
- * Based on a Perl story by Farhad Anklesaria.
- *
- * Modified by Greg Smith, Bucknell University, 24 Nov 1992
- * to handle multiline status replies.
- *
- ---------------------------------------------------- */
-
- #include "gopherd.h"
- #include <signal.h>
-
- #include <stdio.h>
- #include "ext.h"
-
- #define SLEN 255 /* Generic small buffer length */
- #define TMOUT 180 /* 3 minutes is plenty long enough */
-
- int GLOBALsockfd; /* For cleanup */
- char *appname;
- char ftptmp[SLEN] = LIST;
- char query[BUFSIZ]; /* input redirected by inetd */
- char *host, *thing; /* pointers into query */
- int gettingFile = 1;
- int gettingBinary = 0;
- int childpid;
-
- /*** Some forward declarations ***/
- boolean NotText();
- int Abort();
- boolean IsBinaryType();
- void GenerateUniqueFiles();
- void GopherType();
- void Cleanup();
- void RoundEmUp();
- void FailErr();
- int getreply();
- /**************************/
-
- int
- getreply(theStream,inputline,maxlen)
- int theStream;
- char *inputline;
- int maxlen;
- {
- int code = 0;
- char origcode[4];
-
-
- if (DEBUG) fprintf(stderr,"getreply...");
- readline(theStream, inputline, maxlen);
- if (DEBUG) printf(inputline);
- strncpy(origcode, inputline, 3); /*** Stash away the original code ***/
-
- while (inputline[3] == '-') {
- if (readline(theStream, inputline, maxlen)<=0)
- return(-1);
- if (DEBUG) printf(inputline);
-
- if (!isdigit(inputline[0]) && !isdigit(inputline[1]) &&
- !isdigit(inputline[2]))
- inputline[3] = '-';
- else
- /*** Keep going if response code isn't the same as original **/
- if (strncmp(origcode, inputline, 3) != 0)
- inputline[3] = '-';
- }
- return (0);
- }
-
- void
- SendFtpQuery(sockfd, query)
- char *query;
- {
- int sLen, termCh;
- char *at, *cp;
- char inputline[512];
- char ipnum[64];
- char buf[1600]; /*** Nice MTU size ***/
- int tmpfd;
- int ftp_control, ftp_data;
- int ftp_dataport, nRead;
- GopherObj *gs;
-
- /*** hook onto the gs code to do our ftp socket connects ***/
- gs = GSnew();
-
- /** Get ready for some cleanup action **/
- signal(SIGPIPE, Cleanup);
- signal(SIGINT, Cleanup);
- signal(SIGALRM, Cleanup);
-
- if (DEBUG)
- printf("The full query was %s\n", query);
-
- if ((sLen = strlen(query)) <= 2) Abort(sockfd,"No host name specified.");
- host = query;
- at = strchr(query, '@');
-
- if (at == NULL)
- Abort(sockfd, "Not a valid ftp query.");
-
- GenerateUniqueFiles(ftptmp);
- tmpfd = uopen(ftptmp, O_RDWR|O_CREAT,0755);
-
- if (tmpfd < 0)
- Abort(sockfd, "Sorry, out of tmp transfer space!");
-
- thing = at + 1;
- *at = '\0'; /*Sneakily chop it into two strings*/
-
- sLen = strlen(thing);
- termCh = thing[sLen - 1]; /* Grab possible end char: / etc */
-
- if ((termCh == '*') || (termCh == '@')) /* || (termCh == '/') */
- thing[sLen - 1] = '\0';
-
- if (DEBUG)
- printf("At this point host: %s thing: %s\n", host, thing);
-
-
-
- /*** Open an ftp control connection ***/
- GSsetHost(gs, host);
- GSsetPort(gs, 21);
-
- ftp_control = GSconnect(gs);
- if (ftp_control < 0)
- Abort(sockfd, "unable to connect to ftp server!");
-
- /*** Strip off the connection message ***/
- getreply(ftp_control,inputline,sizeof inputline);
-
- if (*inputline != '2')
- /*** Some sort of error, urg! ***/
- Abort(sockfd, inputline +3);
-
- /*** Send username ***/
- writestring(ftp_control, "USER anonymous\r\n");
-
- getreply(ftp_control,inputline,sizeof inputline);
-
- if (*inputline != '3')
- /*** Some sort of error, urg! ***/
- Abort(sockfd, inputline +3);
-
- /** Send password***/
- writestring(ftp_control, "PASS -gopher@");
- inet_netnames(sockfd, inputline, ipnum);
- writestring(ftp_control, inputline);
- writestring(ftp_control, "\r\n");
- if (DEBUG) printf("Password was -gopher@%s\n", inputline);
- getreply(ftp_control,inputline,sizeof inputline);
-
- if (*inputline != '2')
- /*** Some sort of error, urg! ***/
- Abort(sockfd, inputline +3);
-
- /**** Send PASV and set up the data port ***/
- writestring(ftp_control, "PASV\r\n");
-
- getreply(ftp_control,inputline,sizeof inputline);
-
- if (strncmp(inputline, "227", 3))
- Abort(sockfd,inputline +3);
-
- /*** Find out the port number of the data connection ***/
- inputline[strlen(inputline)] = '\0'; /** Zap the right paren **/
- cp = strrchr(inputline, ','); /** lower order octet **/
- if (cp == NULL) Abort(sockfd,"PASV failed- cannot ftp!");
- *cp = '\0';
- cp ++;
- ftp_dataport = atoi(cp);
-
- cp = strrchr(inputline, ','); /** upper octet **/
- if (cp == NULL) Abort(sockfd,"PASV failed- cannot ftp!");
- *cp = '\0';
- cp ++;
- ftp_dataport = atoi(cp) * 256 + ftp_dataport;
- if (DEBUG) printf("Data port is %d\n", ftp_dataport);
-
- GSsetPort(gs, ftp_dataport);
- ftp_data = GSconnect(gs);
- if (ftp_data < 0)
- Abort(sockfd,"Unable to establish data connection!");
-
-
- if (termCh == '/') { /* We have a directory */
- gettingFile = 0;
-
- writestring(ftp_control, "NLST -LF ");
- if (strlen(thing) > 0)
- writestring(ftp_control, thing);
- writestring(ftp_control, "\r\n");
-
- getreply(ftp_control,inputline,sizeof inputline);
-
- if (*inputline != '1')
- Abort(sockfd,inputline + 4);
- }
- else { /* We have a file */
- gettingFile = 1;
- if (gettingBinary = IsBinaryType(thing)) {
- writestring(ftp_control, "TYPE I\r\n");
- getreply(ftp_control,inputline,sizeof inputline);
- if (*inputline != '2')
- Abort(sockfd,"Unable to transfer files in binary");
- }
- writestring(ftp_control, "RETR ");
- writestring(ftp_control, thing);
- writestring(ftp_control, "\r\n");
-
- getreply(ftp_control,inputline,sizeof inputline);
- if (*inputline != '1')
- Abort(sockfd,inputline + 4);
- }
-
- /*** Transfer the data... ***/
- while ((nRead = read(ftp_data, buf, sizeof buf)) > 0)
- writen(tmpfd, buf, nRead);
-
- close(ftp_data);
-
- getreply(ftp_control,inputline,sizeof inputline);
-
- if (*inputline != '2')
- Abort(sockfd,inputline + 3);
-
- writestring(ftp_control, "QUIT\r\n");
-
- getreply(ftp_control,inputline,sizeof inputline);
-
- if (*inputline != '2')
- Abort(sockfd,inputline + 3);
-
- close(ftp_control);
- }
-
- /*--------------------------------*/
- void
- TranslateResults(sockfd)
- int sockfd;
- {
- FILE *fp, *OpenOrDie();
- char buf[BUFSIZ], theName[SLEN];
- int fd, nRead, checkIt;
- char outputline[512];
-
- checkIt = 1;
-
- signal(SIGPIPE, Cleanup);
- signal(SIGINT, Cleanup);
-
- if (gettingFile) {
- if (gettingBinary) { /* icky binary file */
- if (DEBUG)
- printf("Whoa! That's a binary file\n");
- fp = OpenOrDie(ftptmp, "r");
- fd = fileno(fp);
-
- if (DEBUG)
- printf("fd %d\n",fd);
- while ((nRead = read(fd, buf, sizeof buf)) > 0)
- writen(sockfd, buf, nRead);
-
- writen(sockfd, buf, nRead);
- fclose(fp);
- } else { /* must be a nice texty file */
- fp = OpenOrDie(ftptmp, "r");
- while (fgets(buf, sizeof buf, fp) != NULL) {
- if (checkIt) { /* Just peek at it once */
- checkIt = 0;
- if (NotText(buf)) {
- fclose(fp);
- Abort(sockfd,"Sorry. File does not appear to contain text.");
- }
- }
- ZapCRLF(buf);
- FailErr(writestring(sockfd, buf));
- FailErr(writestring(sockfd, "\r\n"));
- }
- fclose(fp);
- FailErr(writestring(sockfd,".\r\n"));
- }
- } else { /* Must be a directory */
- fp = OpenOrDie(ftptmp, "r");
- while (fgets(buf, sizeof buf, fp) != NULL) {
- ZapCRLF(buf);
- GopherType(buf, theName);
- sprintf(outputline, "%s\tftp:%s@%s%s\t%s\t%d\r\n", theName,
- host, thing, buf, Zehostname, GopherPort);
- FailErr(writestring(sockfd, outputline));
- }
- fclose(fp);
- FailErr(writestring(sockfd, ".\r\n"));
- }
-
- Cleanup();
- }
-
- /*--------------------------------*/
-
- FILE *OpenOrDie(file, mode)
- char *file, *mode;
- {
- FILE *fp, *fopen();
- if ((fp = ufopen(file, mode,0755)) != NULL) {
- return(fp);
- } else {
- Cleanup();
- exit(-1);
- }
- return(NULL); /** Shouldn't get here **/
- }
-
-
- /*--------------------------------*/
- boolean
- NotText(buf)
- char * buf;
- {
- int max; char *c;
-
- if ((max = strlen(buf)) >= (BUFSIZ - 50)) max = BUFSIZ - 50;
- for (c = buf; c < (buf + max); c++) {
- if (*c > '~') return(TRUE);
- }
- return(FALSE);
- }
-
- /*--------------------------------*/
-
- int
- Abort(sockfd, complaint)
- int sockfd;
- char *complaint;
- {
- char errmsg[512];
- sprintf(errmsg, "3 Error: %s\r\n.\r\n", complaint);
- writestring(sockfd, errmsg);
- fflush(stdout);
- Cleanup();
- exit(1);
- }
-
- /*--------------------------------*/
-
- boolean
- IsBinaryType(thing)
- char *thing;
- {
- char Gtype, *prefix;
- Extobj *ext;
-
- if (GDCViewExtension(Config, thing, &ext)) {
- Gtype = EXgetObjtype(ext);
-
- if(Gtype == A_FILE || Gtype == A_MACHEX)
- return FALSE;
- else
- return TRUE;
- } else
- return(FALSE);
-
- return TRUE;
- }
-
- /*--------------------------------*/
-
- void
- GenerateUniqueFiles(tmpList)
- char *tmpList;
- {
- char *s;
- int pid;
-
- pid = getpid();
- s = strchr(tmpList, '+');
- sprintf(s, "%d", pid);
- }
-
- /*--------------------------------*/
-
- void
- GopherType(buf, theName)
- char *buf, *theName;
- {
- char Gtype, *prefix;
- int last;
- char tmpName[SLEN];
- Extobj *ext;
-
- last = strlen(buf) -1;
-
- strcpy(tmpName, buf);
- if (buf[last] == '/') {
- tmpName[last] = '\0';
- sprintf(theName, "%c%s", A_DIRECTORY, tmpName);
- return;
- }
- if ((buf[last] == '*') || (buf[last] == '@')) { /* Hack out * and @ */
- buf[last] = '\0';
- tmpName[last] = '\0';
- }
-
- /* At this point we're looking at a file */
- if (GDCViewExtension(Config, buf, &ext)) {
- Gtype = EXgetObjtype(ext);
-
- sprintf(theName, "%c%s", Gtype, tmpName);
- return;
- }
-
- sprintf(theName, "%c%s", A_FILE, tmpName);
- return; /* Some other and hopefully text file */
- }
-
- /*--------------------------------*/
-
- void
- Cleanup()
- {
- unlink(ftptmp);
- if (DEBUG)
- printf("Cleaning up %s\n", ftptmp);
-
- exit(1);
- }
-
- /*--------------------------------*/
- void
- RoundEmUp()
- {
-
- kill(childpid, SIGKILL);
- Cleanup();
- }
-
- /*--------------------------------*/
- void
- FailErr(result)
- int result;
- {
- if (result < 0) {
- Cleanup();
- }
- }
-
- /*--------------------------------*/
-